package com.example.studyFile.asynchronousOptimization;

import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        // 模拟导出数据的业务逻辑
        int batchSize = 2;  // 每次处理500条数据
        List<BasisVo> allData = generateSampleData(10);  // 假设有3000条数据
        AtomicInteger startNumAi = new AtomicInteger(1);  // 起始行号从1开始

        // 模拟分页查询结果数据
        System.out.println("Total data size: " + allData.size());

        // 创建一个线程池
        ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);

        // 计算需要分批次处理的任务数量
        CountDownLatch countDownLatch = new CountDownLatch((allData.size() + batchSize - 1) / batchSize);

        // 按批次进行数据处理
        for (int i = 0; i < allData.size(); i += batchSize) {
            // 获取当前批次的数据
            List<BasisVo> batchData = allData.subList(i, Math.min(i + batchSize, allData.size()));

            // 计算该批次的起始行号，并确保每个批次的行号连续
            int startRowNum = startNumAi.getAndAdd(batchData.size());

            // 使用线程池异步执行当前批次的数据导出任务
            threadPoolExecutor.execute(() -> {
                try {
                    // 模拟 MDC 设置
                    String belongTeamJson = "Team1";
                    String regionJson = "RegionA";
                    System.out.println("Setting MDC data: Team=" + belongTeamJson + ", Region=" + regionJson);

                    // 将 BasisVo 转换为 DTO 对象
                    List<BusinessRankLogBasisDTO> dtoList = batchData.stream()
                            .map(basis -> {
                                BusinessRankLogBasisDTO dto = new BusinessRankLogBasisDTO();
                                // 假设通过 BeanUtils.copyProperties 进行属性复制
                                dto.setName(basis.getName());
                                dto.setValue(basis.getValue());
                                return dto;
                            })
                            .collect(Collectors.toList());

                    // 模拟将数据写入 Excel
                    synchronized ("test") {
                        // 这里模拟 Excel 导出的操作
                        System.out.println("Exporting batch, startRowNum: " + startRowNum + ", data size: " + dtoList.size());
                    }
                } catch (Exception e) {
                    System.err.println("Error during export: " + e.getMessage());
                    throw new RuntimeException(e);
                } finally {
                    // 每个批次任务完成后，调用 countDown()
                    countDownLatch.countDown();
                }
            });
        }

        // 等待所有任务完成
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            System.err.println("Export interrupted: " + e.getMessage());
            throw new RuntimeException(e);
        }

        // 结束后打印完成信息
        System.out.println("Export completed.");
        threadPoolExecutor.shutdown();
    }

    // 生成样本数据
    private static List<BasisVo> generateSampleData(int size) {
        List<BasisVo> data = new ArrayList<>();
        for (int i = 0; i < size; i++) {
            BasisVo vo = new BasisVo();
            vo.setName("Name " + i);
            vo.setValue("Value " + i);
            data.add(vo);
        }
        return data;
    }

    // 模拟 BasisVo 类
    public static class BasisVo {
        private String name;
        private String value;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }

    // 模拟 BusinessRankLogBasisDTO 类
    public static class BusinessRankLogBasisDTO {
        private String name;
        private String value;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }
    }
}
